/**
 * 对象处理相关
 * @packageDocumentation
 * @module objectfuns
 * @preferred
 */

import { isEmpty } from '../commonfuns';

/**
 * 删除对象空值
 * @param {any} o 传入的值
 * @return {any}  处理后的值
 * @example
 * ``` typescript
 * 1. deepDeleteEmptyValue('test') => 'test'
 * 2. deepDeleteEmptyValue(123) => 123
 * 3. deepDeleteEmptyValue([1,2,null]) => [1,2]
 * 4. deepDeleteEmptyValue({i: { x: [1, 2, null] }}) => {i: { x: [1, 2] }}
 */
export function deepDeleteEmptyValue(obj: any) {
  if (isEmpty(obj) || typeof obj === 'number') {
    return obj;
  }
  let newObj = {};
  if (typeof obj === 'string') {
    try {
      obj = JSON.parse(obj);
    } catch (error) {
      return obj;
    }
  }
  if (obj instanceof Array) {
    newObj = [];
  }
  if (obj instanceof Object) {
    for (const attr in obj) {
      if (obj?.hasOwnProperty(attr) && !isEmpty(obj[attr])) {
        if (obj[attr] instanceof Object) {
          // 空数组或空对象不加入新对象(去掉[],{})
          if (
            JSON.stringify(obj[attr]) === '{}' ||
            JSON.stringify(obj[attr]) === '[]'
          ) {
            continue;
          }
          // 属性值为对象,则递归执行去除方法
          newObj[attr] = deepDeleteEmptyValue(obj[attr]);
        } else if (
          typeof obj[attr] === 'string' &&
          ((obj[attr].indexOf('{') > -1 && obj[attr].indexOf('}') > -1) ||
            (obj[attr].indexOf('[') > -1 && obj[attr].indexOf(']') > -1))
        ) {
          // 属性值为JSON时
          try {
            const attrObj = JSON.parse(obj[attr]);
            if (attrObj instanceof Object) {
              newObj[attr] = deepDeleteEmptyValue(attrObj);
            }
          } catch (e) {
            newObj[attr] = obj[attr];
          }
        } else {
          newObj[attr] = obj[attr];
        }
      }
    }
  }
  return newObj;
}

/**
 * 获取具体节点路径
 * @ignore
 */
function getNodePath(node, nodeValue, nodeKey, childrenKey, path: any[] = []) {
  path.push(node);
  if (node[nodeKey] === nodeValue) {
    throw 'GOT IT!';
  }
  if (node[childrenKey] && node[childrenKey].length > 0) {
    for (let i = 0; i < node[childrenKey].length; i++) {
      getNodePath(node[childrenKey][i], nodeValue, nodeKey, childrenKey, path);
    }
  }
  path.pop();
}

/**
 * 查找树结构节点路径
 * @param {*} nodeValue 节点值
 * @param {string} nodeKey 节点键
 * @param {Array} treeArray 树数据
 * @param {string} children 子集键
 */
export function findNodePath(nodeValue, nodeKey, treeArray, childrenKey) {
  const path: any[] = [];
  try {
    for (let i = 0; i < treeArray.length; i++) {
      getNodePath(treeArray[i], nodeValue, nodeKey, childrenKey, path);
    }
  } catch (e) {
    return path;
  }
}

/**
 * 深克隆
 * @param {any} item 传入的值
 * @return {any}  深克隆后的值
 * @example
 * ``` typescript
 * 1. deepClone({ a: 123, b: [{ c: 456 }] }) => { a: 123, b: [{ c: 456 }] }
 * 2. deepClone(null) => null
 * 3. deepClone([123, 456]) => [123, 456]
 */
export function deepClone(item: any): any {
  let copy;
  if (item === null || typeof item !== 'object') {
    return item;
  }
  // array
  if (item instanceof Array) {
    copy = [];
    const len = item.length;
    for (let i = 0; i < len; i++) {
      // 循环深克隆
      copy[i] = deepClone(item[i]);
    }
    return copy;
  }
  // object
  if (item instanceof Object) {
    copy = {};
    for (const val in item) {
      if (Object.prototype.hasOwnProperty.call(item, val)) {
        copy[val] = deepClone(item[val]);
      }
    }
    return copy;
  }
  // date
  if (item instanceof Date) {
    copy = new Date();
    copy.setTime(item.getTime());
    return copy;
  }
  throw new Error("Unable to copy item! Its type isn't supported.");
}

export default { deepDeleteEmptyValue, findNodePath, deepClone };
